package org.testis.orm.refinedclasses;

import java.util.HashMap;
import java.util.LinkedList;
import org.orm.PersistentException;
import org.testis.orm.classes.T_dmap_objectpair;
import org.testis.orm.classes.T_dmap_objectpairCriteria;
import org.testis.orm.classes.T_dmap_objects;
import org.testis.orm.classes.T_dmap_params;
import org.testis.utils.middleware.DynamicMap;


/**
 * 
 * @author Cahit Emir Erel
 */
public class DynamicMapObject extends DynamicMapDesignPart {

    private LinkedList<DynamicMapParameter> m_parameters;
    private T_dmap_objects m_reference;

    /**
     * Constructs a DynamicMapObject with the provided reference
     * 
     * @param object
     *            - Dynamic Map Object reference
     * @throws NullPointerException
     */
    public DynamicMapObject(T_dmap_objects object) {
	initialize();
	setReference(object);
	T_dmap_objectpair[] objectPairList = null;
	try {
	    T_dmap_objectpairCriteria t_dmap_objectpairCriteria = new T_dmap_objectpairCriteria();
	    t_dmap_objectpairCriteria.createObjectCriteria().id.eq(object
		    .getId());
	    objectPairList = t_dmap_objectpairCriteria.listT_dmap_objectpair();
	} catch (PersistentException ex) {
	    System.out.println("UNABLE TO CONNECT TO DATABASE! ABORT!");
	    ex.printStackTrace();
	}
	if (objectPairList != null && objectPairList.length > 0) {
	    DynamicMapParameter[] dparams = new DynamicMapParameter[object
		    .getType().t_dmap_params.size()];
	    for (int i = 0; i < objectPairList.length; i++) {
		T_dmap_params param = DynamicMap.newInstance().getParamById(
			objectPairList[i].getParam().getId());
		if (param != null) {
		    dparams[param.getRank() - 1] = new DynamicMapParameter(
			    param, objectPairList[i], object);
		}
	    }
	    for (int i = 0; i < dparams.length; i++) {
		if (dparams[i] != null) {
		    this.addParameter(dparams[i]);
		}
	    }
	}
    }

    /**
     * 
     */
    private void initialize() {
	m_parameters = new LinkedList<DynamicMapParameter>();
    }

    /**
     * 
     * @return
     * @throws org.orm.PersistentException
     * @throws NullPointerException
     */
    synchronized public DynamicMapObject createRefinedDatabaseCopy()
	    throws PersistentException {
	return new DynamicMapObject(createDatabaseCopy());
    }

    /**
     * 
     * @return
     * @throws org.orm.PersistentException
     * @throws NullPointerException
     */
    private T_dmap_objects createDatabaseCopy() throws PersistentException {
	DynamicMapParameter parameter;
	T_dmap_objects newObject = new T_dmap_objects();
	newObject.setName(getReference().getName());
	newObject.setType(getReference().getType());
	if (newObject.save()) {
	    for (int i = 0; i < getParametersLinkedList().size(); i++) {
		parameter = getParametersLinkedList().get(i);
		if ((parameter.createRefinedDatabaseCopy(newObject)) == null) {
		    throw new PersistentException();
		}
	    }
	    return newObject;
	} else {
	    throw new PersistentException();
	}
    }

    /**
     * 
     * @param parameter
     * @throws NullPointerException
     */
    public void addParameter(DynamicMapParameter parameter) {
	if (parameter == null) {
	    throw new NullPointerException();
	}
	getParametersLinkedList().add(parameter);
    }

    /**
     * 
     * @return
     */
    public DynamicMapParameter[] getParameters() {
	return getParametersLinkedList().toArray(
		new DynamicMapParameter[getParametersLinkedList().size()]);
    }

    /**
     * 
     * @return
     */
    public LinkedList<DynamicMapParameter> getParametersLinkedList() {
	return m_parameters;
    }

    /**
     * 
     * @param name
     * @return
     */
    public DynamicMapParameter getParameterByName(String name) {
	DynamicMapParameter temp;
	for (int i = 0; i < getParametersLinkedList().size(); i++) {
	    temp = getParametersLinkedList().get(i);
	    if (temp.getName().equals(name)) {
		return temp;
	    }
	}
	return null;
    }

    /**
     * 
     * @return
     * @throws org.orm.PersistentException
     * @throws NullPointerException
     */
    @Override
    public boolean delete() throws PersistentException {
	if (deleteParameters()) {
	    return getReference().deleteAndDissociate();
	}
	return false;
    }

    /**
     * 
     * @return
     * @throws org.orm.PersistentException
     */
    public boolean deleteParameters() throws PersistentException {
	if (getParametersLinkedList() != null) {
	    for (; getParametersLinkedList().size() > 0;) {
		if (getParametersLinkedList().getFirst().delete()) {
		    getParametersLinkedList().removeFirst();
		} else {
		    return false;
		}
	    }
	}
	return true;
    }

    /**
     * 
     * @return
     * @throws NullPointerException
     */
    public Integer getId() {
	return getReference().getId();
    }

    /**
     * 
     * @return
     * @throws NullPointerException
     */
    public String getName() {
	return getReference().getName();
    }

    /**
     * 
     * @return
     * @throws NullPointerException
     */
    @Override
    public String getTypeName() {
	try {
	    return getReference().getType().getName();
	} catch (NullPointerException ex) {
	    return "";
	}
    }

    /**
     * 
     * @return
     * @throws NullPointerException
     */
    public String getGroupName() {
	try {
	    return getReference().getType().getGroup().getName();
	} catch (NullPointerException ex) {
	    return "";
	}
    }

    @Override
    public String toString() {
	StringBuffer buffer = new StringBuffer();
	buffer.append("Name:" + getName());
	if (getTypeName() != null
		&& getTypeName().equals("UIDeviceMapContainer")) {
	    if (getReference().t_dmap_designtree != null
		    && getReference().t_dmap_designtree.size() == 1
		    && getReference().t_dmap_designtree.toArray()[0].t_bed_firmware != null
		    && getReference().t_dmap_designtree.toArray()[0].t_bed_firmware
			    .size() == 1) {
		buffer.append(" FW: "
			+ getReference().t_dmap_designtree.toArray()[0].t_bed_firmware
				.toArray()[0].getName());
	    }
	}
	buffer.append("\nType:" + getTypeName() + "\nGroup:" + getGroupName()
		+ "\n");
	buffer.append("Object Id:" + getId() + "\n");
	for (int i = 0; i < getParametersLinkedList().size(); i++) {
	    if (getParametersLinkedList().get(i) != null) {
		buffer.append(getParametersLinkedList().get(i).toString()
			+ "\n");
	    }
	}
	return buffer.toString();
    }

    public T_dmap_objects getReference() {
	return m_reference;
    }

    private void setReference(T_dmap_objects enclosedObject) {
	m_reference = enclosedObject;
    }

    private int compare(DynamicMapObject source) {
	DynamicMapParameter[] list = source.getParameters();
	if (list.length != getParametersLinkedList().size()) {
	    return Comparable.DIFFERENT_PARAMETERS;
	}
	for (int i = 0; i < list.length; i++) {
	    if (!(getParametersLinkedList().get(i).getName()
		    .equals(list[i].getName()) && getParametersLinkedList()
		    .get(i).getReference().getValue()
		    .equals(list[i].getReference().getValue()))) {
		return Comparable.DIFFERENT_PARAMETERS;
	    }
	}
	return Comparable.EXACT;
    }

    public int compare(Comparable source, Comparable treeReference) {
	DynamicMapDesignTreeNode src = (DynamicMapDesignTreeNode) source;
	if (!src.getObject().getGroupName().equals(getGroupName())) {
	    return Comparable.DIFFERENT_TYPE;
	}
	return compare(src.getObject());
    }

    private boolean hasSameStaticParameters(HashMap<String, Object> params,
	    Comparable treeTreference) {
	return true;
    }

    public boolean compareParameters(HashMap<String, Object> params,
	    Comparable treeTreference) {
	return hasSameStaticParameters(params, treeTreference);
    }

    public boolean hasSameRunTimeParams(HashMap<String, Object> params,
	    Comparable treeTreference) {
	return true;
    }

}
